package de.hmm.hwip.service;

import java.util.Hashtable;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.util.tracker.ServiceTracker;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.util.Log;
import android.widget.Toast;
import de.hmm.hwip.general.IAndroidContext;
import de.hmm.hwip.messagehandler.api.IMessageHandler;
import de.hmm.hwip.messagehandler.api.IipcToAndroid;
import de.hmm.hwip.osgi.R;
import de.hmm.hwip.osgi.ipc.ApplicationConnector;
import de.hmm.hwip.osgi.ipc.IpcMessageHandler;
import de.hmm.hwip.osgi.ipc.OsgiIpcImpl;
import de.hmm.hwip.osgi.view.OSGiAdminConsole;

/**
 * Service to receive and redirect messages from hardware connector to messengerhandler
 * also transfers the android application context for data permissions
 * @author johannes mendel
 *
 */
public class MessengerService extends Service implements BundleActivator {
	
	/** Android Service Context **/
	private static Context context;
	
	/** For showing and hiding our notification. */
    NotificationManager mNM;
    
    /** Interprocess communication Interface for OSGi **/
    private static IMessageHandler osgiIpcService;
   
    /** IPC Interface getting messages from OSGi */
    private IipcToAndroid androidService;
    
    /** Android Context Interface transfering App Context to OSGi */
    private IAndroidContext contextService;
    
    /** OSGi IPC Service tracker */
    private static ServiceTracker serviceTracker;

    /** OSGI DB ServiceTracker and Service */
    static IAndroidContext dbService;
    
    /** OSGI Bundle Context **/
    private static BundleContext bundleContext;
    
	/** Service Tag */
	private static final String TAG = "IPC Service";
	
	/**android Method to bin Service **/
    @Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return mMessenger.getBinder();
	}
    
	 /**
     * Target we publish for clients to send messages to IncomingHandler.
     */
    final Messenger mMessenger = new Messenger(new IpcMessageHandler());
    
    @Override
    public void onCreate() {
    	mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);

    	context = getApplicationContext();
    	
        // Display a notification about us starting.
    	if(Build.VERSION.SDK_INT >= 12)
    		showNotification();
    }
    
    /*
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Toast.makeText(this, "service starting", Toast.LENGTH_LONG).show();
        System.out.println("startId: " + startId);
        // For each start request, send a message to start a job and deliver the
        // start ID so we know which request we're stopping when we finish the job
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        mServiceHandler.sendMessage(msg);
        
        // If we get killed, after returning from here, restart
        return START_STICKY;
    }
    */
    
    @Override
    public void onDestroy() {
    	// Cancel the persistent notification.
        mNM.cancel(R.string.msg_service_stopped);

        // Tell the user we stopped.
        Toast.makeText(this, R.string.msg_service_stopped, Toast.LENGTH_SHORT).show();
    }

    /** OSGI Activator start to register OSGI Service on Framework **/
	@Override
	public void start(BundleContext context) throws Exception {
		bundleContext = context;
		serviceTracker = new ServiceTracker(context, IMessageHandler.class.getName(), null );
		serviceTracker.open();
		
    	androidService = new OsgiIpcImpl();
    	contextService = new ApplicationConnector();
    	
    	Hashtable<String, Object> aparams = new Hashtable<String, Object>();
    	aparams.put( org.osgi.framework.Constants.SERVICE_PID, IipcToAndroid.class.getName());
    	aparams.put( org.osgi.framework.Constants.SERVICE_DESCRIPTION,"Provides IPC Service");
    	context.registerService(IipcToAndroid.class.getName(), androidService, aparams);
    	
    	Hashtable<String, Object> cparams = new Hashtable<String, Object>();
    	cparams.put( org.osgi.framework.Constants.SERVICE_PID, IAndroidContext.class.getName());
    	cparams.put( org.osgi.framework.Constants.SERVICE_DESCRIPTION,"Provides Android Context Service");
    	context.registerService(IAndroidContext.class.getName(), contextService, cparams);
    	
	}

	@Override
	public void stop(BundleContext arg0) throws Exception {
		//m_context = null;
		serviceTracker.close();
	}
	
	/**
	 * Getter for ServiceTracker
	 * @return serviceTracker
	 */
	private static ServiceTracker getServiceTracker(){
		if(serviceTracker != null){
			return MessengerService.serviceTracker;
		}else
			return null;
	}
	
	/**
	 * Method to send messages to OSGi-Romte-Service
	 * @param msg = Bundledata from type Message
	 */
	public static boolean sendMsg(Message msg) throws Exception{
		if(getServiceTracker() != null){
			osgiIpcService = (IMessageHandler) getServiceTracker().getService();
		}else
			Log.w(TAG, "ServiceTracker is: " + serviceTracker);
		
		if(osgiIpcService != null && msg != null){
				osgiIpcService.startAction("hwip.processing.Sys_Device", msg.arg1, msg.getData(), bundleContext);
			return true;
		}else{
			Log.w("IPC Service", "Remote message service is " + osgiIpcService + " at message: " + msg.toString());
			return false;
		}
	}
	
	/**Getter for Android App-Context */
	public static Context getCotnext(){
		return context;
	}
	
	/** Servicetracker for Storage Service **
	 * if dbService is coming online tracker will notice and send Applicationcontext

	private class Customizer implements ServiceTrackerCustomizer{

		@Override
		public Object addingService(final ServiceReference reference) {
			System.out.println("---------> DB Service is connected <---------");
			dbService = (IAndroidContext) bundleContext.getService(reference);
			if(dbService != null){
				dbService.transferContext(context);
			}
			return dbService;
		}
		
		@Override
		public void modifiedService(ServiceReference arg0, Object arg1) {
			// nothing to do
			
		}

		@Override
		public void removedService(ServiceReference arg0, Object arg1) {
			// nothing to do
			
		}
		
	}*/
	
	 
	/**
	 * Show a notification while this service is running.
	 */
	private void showNotification() {

		 CharSequence text = getText(R.string.msg_service_started);
		 Context context = getApplicationContext();
		 Intent notificationIntent = new Intent(this, OSGiAdminConsole.class);
		 PendingIntent contentIntent = PendingIntent.getActivity(this, R.string.msg_service_started, notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);
		 
		 NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
		 
		 Notification.Builder notifi = new Notification.Builder(context);
		 notifi.setContentIntent(contentIntent);
		 notifi.setContentTitle(getText(R.string.app_name));
		 notifi.setContentText(text);
		 notifi.setSmallIcon(R.drawable.icon);
		 
		 Notification n = notifi.getNotification();
		 nm.notify(R.string.msg_service_started, n);
	 }
	 

	 /* Test Methode zum Zeitversetzten verschicken 
	 private void sendtimedmsg(final long time){
		 Thread t = new Thread(){
			 public void run(){
				 Calendar calendar = Calendar.getInstance(TimeZone.getDefault());		
				 long now = calendar.getTimeInMillis();
				 while(true){
					 Calendar cal = Calendar.getInstance(TimeZone.getDefault());		
					 long now2 = cal.getTimeInMillis();
					 //System.out.println(now + " : " + (now2 - 10000 ));
					 if(now < (now2 - time) ){
						 Bundle bun = new Bundle();
						 bun.putString("1", "blablub");
						 Message msg = new Message();
						 msg.setData(bun);
						 msg.obtain(null, MSG_DATA_BUNDLE, this.hashCode(), 0 );
						 try {
							sendMsg(msg);
						} catch (Exception e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						 break;
					 }else if(now == calendar.getTimeInMillis() - time + 1000 )
						 break;	
				 }
			 }
		 };
		 t.start();
	 }*/
}
